#include "htil.hpp"

class Parse
{
private:
    Logging* log_point_;
    std::string input_path_;
    std::string output_path_;
    std::string base_url_;
    bool EnumFile(std::vector<std::string> *file_list)
    {
        namespace fs = boost::filesystem;
        fs::path root_path(input_path_);
        // 如果不存在
        // 使用参见 https://www.cnblogs.com/Lilu-1226/p/10773263.html
        if(!fs::exists(root_path))
        {
            std::cerr << "路径不存在" << std::endl;
            return false;
        }        
        fs::recursive_directory_iterator end_iter;
        for(fs::recursive_directory_iterator iter(root_path); iter != end_iter; iter++)
        {
            // 如果不是普通文件就跳过 比如说目录
            if(!fs::is_regular_file(*iter))
            {   
                continue;
            }
            // 判断后缀是否为.html 如果不是 则跳过
            if(iter->path().extension() != ".html")
            {
                continue;
            }

            // 到这里就代表是我们要的网页
            file_list->push_back(iter->path().string());
        }
        return true;
    }
    bool ParseUrl(const std::string& file_path, std::string* doc_url)
    {
        *doc_url = base_url_ + file_path.substr(input_path_.length(), -1);
        return true;
    }
    bool ParseContent(const std::string& html, std::string* doc_content)
    {
        // 先标记是否为正文 碰到<则进行标签模式 这个我们不要 碰到>则进入正文模式 这个我们需要
        bool is_content = false;
        for(const char& c: html)
        {
            // std::cout << c ;
            if(is_content && c == '<')
            {
                is_content = false;
            }
            else if(!is_content && c == '>')
            {
                is_content = true;
            }
            else
            {
                if(is_content)
                {
                    doc_content->push_back(c == '\n' ? ' ' : c);
                }
            }
        }
        return true;
    }
    bool ParseTitle(const std::string& html, std::string* doc_title, const std::string& title_begin_flag, const std::string title_end_flag)
    {
        int title_begin_pos = html.find(title_begin_flag);
        if(title_begin_pos == std::string::npos)
        {
            log_point_->WriteLogToDoc("WARING", "找不到标题头标记位置", common::GetTime());
            return false;
        }
        int title_end_pos = html.find(title_end_flag, title_begin_pos);
        if(title_end_pos == std::string::npos)
        {
            log_point_->WriteLogToDoc("WARING", "找不到标题尾标记位置", common::GetTime());
            return false;
        }
        *doc_title = html.substr(title_begin_pos + title_begin_flag.length(), title_end_pos - title_begin_pos - title_begin_flag.length());
        return true;
    }
    bool ParseFile(const std::string& file_path, DocInfo* doc)
    {
        std::string html;
        const std::string title_begin_flag = "<title>";
        const std::string title_end_flag = "</title>";
        // 1. 先读取文件内容
        bool ret = common::Read(file_path, &html);
        // k u 反注释
        if (!ret)
        {
            log_point_->WriteLogToDoc("WARING", "读取文件失败 文件路径为 " + file_path, common::GetTime());
            return false;
        }
        
        // 2. 解析标题
        if (!ParseTitle(html, &(doc->docTitle_), title_begin_flag, title_end_flag))
        {
            log_point_->WriteLogToDoc("WARING", "解析标题失败", common::GetTime());
            return false; 
        }
        // 3. 解析url
        if (!ParseUrl(file_path, &(doc->docUrl_)))
        {
            log_point_->WriteLogToDoc("WARING", "解析url失败", common::GetTime());
            return false;
        }
        // 4. 解析内容
        if (!ParseContent(html, &(doc->docContent_)))
        {
            log_point_->WriteLogToDoc("WARING", "解析内容失败", common::GetTime());
            return false;
        }
        return true;
    }
public:
    bool init(Logging* log_point_p, const std::string input_path = "", const std::string out_path = "", const std::string base_url = "")
    {
        log_point_ = log_point_p;
        input_path_ = input_path;
        output_path_ = out_path;
        base_url_ = base_url;
        // 1. 进行文件枚举
        // 存放文件枚举路径
        std::ofstream output_file(output_path_.c_str());
        std::vector<std::string> file_list;
        if(!EnumFile(&file_list))
        {
            log_point_->WriteLogToDoc("ERROR", "枚举错误 检查是否路径不存在", common::GetTime());
            return false;
        }
        std::cout << "[SUCCESS] 枚举文件完毕, 文件数量: " << file_list.size() << " " << common::GetTime() << std::endl;
        log_point_->WriteLogToDoc("SUCCESS", " 枚举文件完毕, 文件数量: " + std::to_string(file_list.size()), common::GetTime());
        // 2. 进行文件解析
        size_t total = 0;
        for(std::string & tmp: file_list)
        {
            // std::cout << tmp << std::endl;
            DocInfo doc;
            if(ParseFile(tmp, &doc))
            {
                common::WriteOut(doc, output_file);
                ++total;
            }
        }
        std::cout << "[SUCCESS] 解析文件完毕, 解析数量: " << total << " " << common::GetTime() << std::endl;
        log_point_->WriteLogToDoc("SUCCESS", " 解析文件完毕, 解析数量: " + std::to_string(total), common::GetTime());
        output_file.close();
        return true;
    }
    Parse() {}
};
